//
//  CALayerDelegateViewController.m
//  CoreAnimation
//
//  Created by 张国文 on 16/10/9.
//  Copyright © 2016年 hangzhouyijiyin. All rights reserved.
//

#import "CALayerDelegateViewController.h"

@interface CALayerDelegateViewController ()

@property (nonatomic, strong) UIView *backGroundView; // 底层view
@property (nonatomic, strong) CALayer *blueLayer; // 测试的layer

@end

@implementation CALayerDelegateViewController

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:YES];
    //[self.blueLayer removeFromSuperlayer];
    self.blueLayer.delegate = nil;
    
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];
    
  
    
    self.backGroundView = [[UIView alloc] initWithFrame:self.view.bounds];
    self.backGroundView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:_backGroundView];
    
    self.blueLayer = [[CALayer alloc] init];
    self.blueLayer.frame = CGRectMake(50, 50, 100, 100);
    self.blueLayer.backgroundColor = [UIColor blueColor].CGColor;
    self.blueLayer.delegate = self;
    self.blueLayer.contentsScale = [UIScreen mainScreen].scale;
    [self.backGroundView.layer addSublayer:self.blueLayer];
    [self.blueLayer display]; // 绘制redraw
    self.blueLayer.opaque = NO; // 以后在研究，不是太懂
    
    /**
     *
     *
     *  layer方法响应链有两种:
     1. [layer setNeedDisplay] -> [layer displayIfNeed] -> [layer display] -> [layerDelegate displayLayer:]
     2. [layer setNeedDisplay] -> [layer displayIfNeed] -> [layer display] -> [layer drawInContext:] -> [layerDelegate drawLayer: inContext:]
     说明一下，如果layerDelegate实现了displayLayer:协议，之后layer就不会再调用自身的重绘代码。
     layer的代理对应两个方法，即：- (void)displayLayer:(CALayer *)layer和- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx，要使用这两个方法就要设置代理
     */

}

// 自己的理解：displayerLayer,和drawLayer inContext为layer的代理方法，这个可以在VC中使用(layer自身当然可以使用)，方便图层的绘制;并且displayerLayer如果执行就不会执行drawLayer inContext了。drawLayer inContext在调用之前会调用drawInContext(该方法为系统自动调用)方法确定绘制的大小(在这个方法里面可以绘制内容)，默认为layer层的bounds大小,调用setNeedDisplay未标记需要调用diaplay方法进行重绘，displayIfNeed为需要立即重绘，通常直接调用display就行了

// 需要非常注意的地方：在VC中使用layer层的代理的时候，一定要在视图消失的时候移除该layer或者将该layer的代理设为nil，要不然会发生崩溃，原因不明。

/**
 补充说明：
 *  我们在blueLayer上显式地调用了-display。不同于UIView，当图层显示在屏幕上时，CALayer不会自动重绘它的内容。它把重绘的决定权交给了开发者。
 
 尽管我们没有用masksToBounds属性，绘制的那个圆仍然沿边界被裁剪了。这是因为当你使用CALayerDelegate绘制寄宿图的时候，并没有对超出边界外的内容提供绘制支持。
 */


//- (void)displayLayer:(CALayer *)layer
//{
//    NSLog(@"displayLayer执行了");
//    layer.contents = (__bridge id _Nullable)([UIImage imageNamed:@"图片一"].CGImage);
//}


- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    NSLog(@"drawLayer执行了");
    NSLog(@"layer层的大小：%@", [NSValue valueWithCGRect:layer.bounds]);
    /**
     *  使用UiKit，你只能在当前上下文中绘图，所以如果你当前处于UIGraphicsBeginImageContextWithOptions函数或drawRect：方法中，你就可以直接使用UIKit提供的方法进行绘图。如果你持有一个context：参数，那么使用UIKit提供的方法之前，必须将该上下文参数转化为当前上下文。幸运的是，调用UIGraphicsPushContext 函数可以方便的将context：参数转化为当前上下文，记住最后别忘了调用UIGraphicsPopContext函数恢复上下文环境。
     */
//    layer.backgroundColor = [UIColor yellowColor].CGColor;
    UIGraphicsPushContext(ctx);
    // ctx 为绘制的上下文 即CGContextRef
    CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
    CGContextSetLineWidth(ctx, 2);
    CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 100, 100));
    CGContextStrokePath(ctx);
    UIGraphicsPopContext();
}




@end
